/**
 * Crypto helpers for login-time password protection.
 * - RSA-OAEP (SHA-256) encrypt using a PEM public key (spki)
 * - SHA-256 hashing as optional helper
 */

function base64ToArrayBuffer(b64: string): ArrayBuffer {
  const binary = atob(b64)
  const len = binary.length
  const bytes = new Uint8Array(len)
  for (let i = 0; i < len; i++) bytes[i] = binary.charCodeAt(i)
  return bytes.buffer
}

function arrayBufferToBase64(buf: ArrayBuffer): string {
  const bytes = new Uint8Array(buf)
  let binary = ''
  const chunk = 0x8000
  for (let i = 0; i < bytes.length; i += chunk) {
    const sub = bytes.subarray(i, i + chunk)
    binary += String.fromCharCode(...Array.from(sub))
  }
  return btoa(binary)
}

function pemToArrayBuffer(pem: string): ArrayBuffer {
  const clean = pem
    .replace(/-----BEGIN [^-]+-----/g, '')
    .replace(/-----END [^-]+-----/g, '')
    .replace(/\s+/g, '')
  return base64ToArrayBuffer(clean)
}

export async function importRsaPublicKeyFromPem(pem: string): Promise<CryptoKey> {
  const spki = pemToArrayBuffer(pem)
  return crypto.subtle.importKey(
    'spki',
    spki,
    { name: 'RSA-OAEP', hash: 'SHA-256' },
    false,
    ['encrypt']
  )
}

export async function rsaEncryptBase64(plainText: string, pemPublicKey: string): Promise<string> {
  const key = await importRsaPublicKeyFromPem(pemPublicKey)
  const enc = new TextEncoder().encode(plainText)
  const cipher = await crypto.subtle.encrypt(
    { name: 'RSA-OAEP' },
    key,
    enc
  )
  return arrayBufferToBase64(cipher)
}

export async function sha256Hex(text: string): Promise<string> {
  const data = new TextEncoder().encode(text)
  const digest = await crypto.subtle.digest('SHA-256', data)
  const bytes = Array.from(new Uint8Array(digest))
  return bytes.map(b => b.toString(16).padStart(2, '0')).join('')
}
